package satir.record;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Observable;
import java.util.Observer;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import satir.framework.JSONIOPerformer.JSONIOPerformerJSONDecodeException;
import satir.framework.JSONIOPerformer.JSONIOPerformerReadException;

/**
 * The Class GameRecord.
 * @version 3.0 April 2012
 * @author Creative Family
 */
public class GameRecord extends SavedEntity implements Observer {

    /** The version. */
    private String version;

    /** The play date. */
    private Date playDate;

    /** The records. */
    private ArrayList<Recordable> records;

    /**
     * Instantiates a new game record.
     * @param dBfn
     *            the dB filename
     * @param dBDir
     *            the dB directory
     * @throws JSONIOPerformerReadException
     *             the jSONIO performer read exception
     * @throws JSONIOPerformerJSONDecodeException
     *             the jSONIO performer json decode exception
     * @throws JSONFileInvalidException
     *             the jSON file invalid exception
     */
    public GameRecord(final String dBfn, final String dBDir)
	    throws JSONIOPerformerReadException,
	    JSONIOPerformerJSONDecodeException, JSONFileInvalidException {
	super(dBfn, dBDir);
	try {
	    getJSONObject().put("records", new JSONArray());
	    DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
	    playDate = new Date();
	    String todayDate = dateFormat.format(playDate);
	    getJSONObject().put("playDate", todayDate);
	} catch (JSONException e) {
	    // TODO Auto-generated catch block
	    e.printStackTrace();
	}
    }

    /**
     * Instantiates a new game record.
     */
    public GameRecord() {
	super();
    }

    /**
     * Adds the record.
     * @param record
     *            the record
     */
    public void addRecord(final Recordable record) {
	records.add(record);
	JSONObject recordJson = new JSONObject();
	try {
	    recordJson.put("player", record.getPlayer());
	    recordJson.put("key", record.getKey());
	    recordJson.put("cardType", record.getClassType());
	    JSONArray action = new JSONArray(record.getAction());
	    recordJson.put("action", action);
	    JSONArray records = getJSONObject().getJSONArray("records");
	    records.put(recordJson);
	} catch (JSONException e) {
	    // TODO Auto-generated catch block
	    e.printStackTrace();
	}
    }

    /**
     * Gets the records.
     * @param profile
     *            the profile
     * @return the records
     */
    public ArrayList<Recordable> getRecords(final Profile profile) {
	ArrayList<Recordable> newRecords = new ArrayList<Recordable>();

	for (int i = 0; i < records.size(); i++) {
	    Recordable record = records.get(i);

	    if (record.getPlayer().equals(profile.getName())) {
		newRecords.add(record);
	    }
	}
	return newRecords;
    }

    /**
     * Create new JSON.
     */
    @Override
    protected void createNewToJSON() {
	try {
	    getJSONObject().put("records", new JSONArray());
	    DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
	    playDate = new Date();
	    String todayDate = dateFormat.format(playDate);
	    getJSONObject().put("playDate", todayDate);
	} catch (JSONException e) {
	    // TODO Auto-generated catch block
	    e.printStackTrace();
	}
    }

    /**
     * Gets appellation.
     * @return appellation
     */
    @Override
    protected String getAppellation() {
	return "GameRecord";
    }

    /**
     * Initialize record objects.
     */
    @Override
    protected void initializeEssentialObjects() {
	// Initialize essential objects
	records = new ArrayList<Recordable>();
    }

    /**
     * Initialize record from JSON.
     * @param json
     *         the JSON object.
     * @throws JSONException
     *          JSONException
     */
    @Override
    protected void initializeFromJSON(final JSONObject json) throws JSONException {
	playDate = new Date(json.getString("playDate"));
	JSONArray tmpRecords = json.getJSONArray("records");

	for (int i = 0; i < tmpRecords.length(); i++) {
	    JSONObject current = tmpRecords.getJSONObject(i);
	    Recordable record = new Record(current.getString("key"),
		    current.getString("cardType"), current.get("action")
			    .toString(), current.getString("player"));

	    records.add(record);
	}
    }

    /**
     * Update record.
     * @param arg0
     *         the Observable object.
     * @param arg1
     *         the object.
     */
    @Override
    public void update(final Observable arg0, final Object arg1) {
	if (arg1 instanceof Recordable) {
	    Recordable target = (Recordable) arg1;
	    if (!target.getIsIgnoreRecord()) {
		addRecord(target);
	    }
	}
    }

    /**
     * The Class Record.
     */
    public class Record implements Recordable {

	/** The key. */
	private String key;

	/** The class type. */
	private String classType;

	/** The action. */
	private String action;

	/** The player. */
	private String player;

	/**
	 * Instantiates a new record.
	 * @param key
	 *            the key
	 * @param classType
	 *            the class type
	 * @param action
	 *            the action
	 * @param player
	 *            the player
	 */
	public Record(final String key, final String classType, final String action, final String player) {
	    this.action = action;
	    this.key = key;
	    this.classType = classType;
	    this.player = player;
	}

	/**
	 * Gets the key.
	 * @return key
	 */
	@Override
	public String getKey() {
	    return key;
	}

	/**
	 * Gets class type.
	 * @return class type
	 */
	@Override
	public String getClassType() {
	    return classType;
	}

	/**
	 * Gets the action.
	 * @return action
	 */
	@Override
	public String getAction() {
	    return action;
	}

	/**
	 * Gets player.
	 * @return player.
	 */
	@Override
	public String getPlayer() {
	    return player;
	}

	/**
	 * Gets the status of record.
	 * @return true if ignore record, otherwise false
	 */
	@Override
	public boolean getIsIgnoreRecord() {
	    return false;
	}
    }
}
